/* gcc -g -O2 -Wall -o egueb_svg_bench egueb_svg_bench.c `pkg-config --cflags --libs egueb_svg enesim librsvg-2.0` */

#include <stdio.h>
#include <unistd.h>
#include <getopt.h>

#include <librsvg/rsvg.h>
#include <librsvg/rsvg-cairo.h>

#include <Egueb_Svg.h>

int verbose = 0;
int with_librsvg = 0;
int with_egueb_svg = 0;

static void _help(void)
{
	printf("Usage: egueb_svg_bench OPTIONS FILE\n");
	printf("Where OPTIONS can be on of the following\n");
	printf("-v, --verbose Be verbose\n");
	printf("-h, --help This help message\n");
	printf("-r, --librsvg Use librsvg for the benchmak\n");
	printf("-e, --egueb_svg Use egueb_svg for the benchmark\n");
	printf("And FILE is the svg file you want to test\n");
}

static double
_time_get(void)
{
	struct timeval timev;

	gettimeofday(&timev, NULL);
	return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
}

static void
_rsvg_bench(const char *filename, double *parsing, double *rendering)
{
	RsvgHandle *rsvg;
	RsvgDimensionData dim;
	int w, h;
	cairo_surface_t *surface;
	cairo_t *cr;
	unsigned int *data;
	double t0, t1;

	rsvg_init();

	t0 = _time_get();

	rsvg = rsvg_handle_new_from_file(filename, NULL);
	rsvg_handle_set_dpi(rsvg, 75.0);  // probably not needed
	rsvg_handle_get_dimensions(rsvg, &dim);

	t1 = _time_get();
	*parsing = t1 - t0;

	t0 = _time_get();

	w = dim.width;
	h = dim.height;
	data = calloc(1, sizeof(unsigned int) * w * h);
	surface = cairo_image_surface_create_for_data((unsigned char *)data,
						      CAIRO_FORMAT_ARGB32,
						      w, h, w * sizeof(unsigned int));
	cr = cairo_create(surface);
	rsvg_handle_render_cairo(rsvg, cr);

	t1 = _time_get();
	*rendering = t1 - t0;
	//printf("size rsvg : %d %d\n", w, h);

	if (verbose)
	{
		cairo_surface_write_to_png(surface, "librsvg_out.png");
	}
	rsvg_term();
}

static void
_egueb_svg_bench(const char *filename, double *parsing, double *rendering)
{
	Egueb_Dom_Node *doc;
	Egueb_Dom_Node *topmost;
	Enesim_Stream *im;
	Enesim_Surface *s = NULL;
	Enesim_Log *log = NULL;
	double w, h;
	double t0, t1;

	egueb_svg_init();

	t0 = _time_get();

	im = enesim_stream_file_new(filename, "r+");
	if (!im)
	{
		printf("no doc\n");
		goto no_file;
	}
	doc = egueb_svg_document_new(NULL);
	egueb_dom_parser_parse(im, doc);
	enesim_stream_free(im);

	egueb_dom_document_element_get(doc, &topmost);
	if (!topmost)
	{
		printf("no topmost\n");
		goto no_topmost;
	}

	t1 = _time_get();
	*parsing = t1 - t0;

	/* rendering */
	t0 = _time_get();

	egueb_dom_document_process(doc);
	egueb_svg_document_width_set(doc, 640);
	egueb_svg_document_height_set(doc, 480);
	egueb_svg_document_actual_width_get(doc, &w);
	egueb_svg_document_actual_height_get(doc, &h);

	s = enesim_surface_new(ENESIM_FORMAT_ARGB8888, lround(w), lround(h));
	if (s)
	{
		/* finally draw */
		if (!egueb_svg_element_svg_draw(topmost, s, ENESIM_ROP_FILL,
			NULL, 0, 0, &log))
		{
			enesim_log_dump(log);
		}
	}

	t1 = _time_get();
	*rendering = t1 - t0;
	//printf("size egueb_svg : %f %f\n", w, h);

	if (s)
	{
		if (verbose)
		{
			Enesim_Buffer *b;
			b = enesim_surface_buffer_get(s);
			enesim_image_file_save("egueb_svg_out.png", b, NULL);
			enesim_buffer_unref(b);
		}
		enesim_surface_unref(s);
	}
	egueb_dom_node_unref(topmost);
no_topmost:
	egueb_dom_node_unref(doc);
no_file:
	egueb_svg_shutdown();
}

int main(int argc, char *argv[])
{
	char *short_options = "vhre";
	struct option long_options[] = {
		{"verbose", 0, 0, 'v'},
		{"help", 0, 0, 'h'},
		{"librsvg", 0, 0, 'r'},
		{"egueb_svg", 0, 0, 'e'},
		{0, 0, 0, 0}
	};
	int c;
	int option;
	extern int optind;
	double rparse = 0, eparse = 0;
	double rrender = 0, erender = 0;

	/* handle the parameters */
	while ((c = getopt_long(argc, argv, short_options, long_options,
			&option)) != -1)
	{
		switch (c)
		{
			case 'h':
			_help();
			return 0;

			case 'v':
			verbose = 1;
			break;

			case 'r':
			with_librsvg = 1;
			break;

			case 'e':
			with_egueb_svg = 1;
			break;

			default:
			break;
		}
	}
	if (optind >= argc)
	{
		_help();
		return 0;
	}

	if (with_librsvg)
	{
		_rsvg_bench(argv[optind], &rparse, &rrender);
	}
	if (with_egueb_svg)
	{
		_egueb_svg_bench(argv[optind], &eparse, &erender);
	}

	if (verbose)
	{
		if (with_egueb_svg && with_librsvg)
		{
			printf("file\tegueb_svg parse\tlibrsvg parse\tegueb_svg render\tlibrsvg render\n");
			printf("%s\t%E\t%E\t%E\t%E\n", argv[optind], eparse, rparse, erender, rrender);
		}
		else if (with_egueb_svg)
		{
			printf("file\tegueb_svg parse\tegueb_svg render\n");
			printf("%s\t%E\t%E\n", argv[optind], eparse, erender);
		}
		else if (with_librsvg)
		{
			printf("file\tlibrsvg parse\tlibrsvg render\n");
			printf("%s\t%E\t%E\n", argv[optind], rparse, rrender);
		}
	}
	return 0;
}
